import hashlib
import time
import json
import requests
from urllib.parse import urlparse

class Block:
    def __init__(self, index, timestamp, data, previous_hash):
        self.index = index
        self.timestamp = timestamp
        self.data = data
        self.previous_hash = previous_hash
        self.nonce = 0
        self.hash = self.calculate_hash()

    def calculate_hash(self):
        data = str(self.index) + str(self.timestamp) + str(self.data) + str(self.previous_hash) + str(self.nonce)
        return hashlib.sha256(data.encode()).hexdigest()

    def mine_block(self, difficulty):
        target = '0' * difficulty
        while self.hash[:difficulty] != target:
            self.nonce += 1
            self.hash = self.calculate_hash()

    def to_dict(self):
        return {
            'index': self.index,
            'timestamp': self.timestamp,
            'data': self.data,
            'previous_hash': self.previous_hash,
            'nonce': self.nonce,
            'hash': self.hash
        }

class Blockchain:
    def __init__(self):
        self.chain = [self.create_genesis_block()]
        self.difficulty = 4
        self.nodes = set()

    def create_genesis_block(self):
        return Block(0, time.time(), "Genesis Block", "0")

    def get_latest_block(self):
        return self.chain[-1]

    def add_block(self, new_block):
        new_block.previous_hash = self.get_latest_block().hash
        new_block.mine_block(self.difficulty)
        self.chain.append(new_block)

    def is_chain_valid(self):
        for i in range(1, len(self.chain)):
            current_block = self.chain[i]
            previous_block = self.chain[i - 1]
            if current_block.hash != current_block.calculate_hash():
                return False
            if current_block.previous_hash != previous_block.hash:
                return False
        return True

    def register_node(self, node_url):
        parsed_url = urlparse(node_url)
        self.nodes.add(parsed_url.netloc)

    def broadcast_block(self, block):
        for node in self.nodes:
            url = f"http://{node}/add_block"
            headers = {'Content-Type': 'application/json'}
            requests.post(url, data=json.dumps(block.to_dict()), headers=headers)

# 创建区块链实例
blockchain = Blockchain()

# 添加区块
def add_block(block_data):
    block = Block(block_data['index'], block_data['timestamp'], block_data['data'], block_data['previous_hash'])
    blockchain.add_block(block)

# 注册节点
def register_node(node_url):
    blockchain.register_node(node_url)

# 启动示例

# 注册节点
register_node('http://localhost:10250')
register_node('http://localhost:8080')

# 添加区块
add_block({
    'index': 1,
    'timestamp': time.time(),
    'data': 'Block 1 data',
    'previous_hash': blockchain.get_latest_block().hash
})

# 广播区块
latest_block = blockchain.get_latest_block()
blockchain.broadcast_block(latest_block)